Skip to content

[lua] Add lua.Lib.getModuleVarargs() for module-level varargs capture#12602

Open
jdonaldson wants to merge 1 commit intoHaxeFoundation:developmentfrom
jdonaldson:lua-global-varargs
Open

[lua] Add lua.Lib.getModuleVarargs() for module-level varargs capture#12602
jdonaldson wants to merge 1 commit intoHaxeFoundation:developmentfrom
jdonaldson:lua-global-varargs

Conversation

@jdonaldson
Copy link
Member

@jdonaldson jdonaldson commented Feb 13, 2026

Summary

  • Addresses [lua] Global Var Args #10753
  • Environments like ComputerCraft pass script arguments via module-level ... (varargs) rather than populating _G.arg. The generated Lua wraps everything in functions, so ... becomes inaccessible.
  • Adds lua.Lib.getModuleVarargs() — an opt-in API that returns the module-level varargs as a Table<Int, String>. Users can convert to an array with Table.toArray().
  • The runtime helper (_hx_module_varargs = {...}) is only included in the output when getModuleVarargs() is actually used (gated behind DCE feature detection).

Test plan

  • make haxe builds successfully
  • All 11,696 Lua unit tests pass
  • Verified getModuleVarargs() captures args when invoked as lua script.lua arg1 arg2
  • Verified the runtime helper is NOT included when getModuleVarargs() is not called

@tobil4sk
Copy link
Member

Sys.args() documentation states:

Returns all the arguments that were passed in the command line.

If Sys.args() can now contain values passed using loadfile instead of via the cli, then it is deviating from the specified behaviour.

Also, just because loadfile was used to load the current module, doesn't mean that _G.arg is necessarily nil. The current patch still gives no way to access {...} if _G.arg is not nil.

Expand for sample lua code where this can occur
-- wrapper.lua
local main = loadfile("main.lua")
main("load", "file", "args")
-- main.lua
print("_G.arg = " .. table.concat(_G.arg, " "))
print("{...} = " .. table.concat({...}, " "))
$ lua wrapper.lua real cli args
_G.arg = real cli args
{...} = load file args

I also think it's bad practice to overwrite a global value like _G.arg.

We should also avoid injecting more unconditionally included lua code. Even if it's one line now, it builds up gradually and one of the most common complaints about the lua target is the boilerplate required for simple programs. It is especially something to consider when only some users need it but it is added to everyone's code. Using define feature here to conditionally generate the extra line avoids this problem.

Maybe it's better to have a new method like lua.Lib.getModuleVarargs()? That avoids messing with the behaviour of Sys.args and gives full control to the user when _G.arg and {...} both exist but are different.

@skial skial mentioned this pull request Feb 19, 2026
1 task
@jdonaldson jdonaldson force-pushed the lua-global-varargs branch 2 times, most recently from ed03f19 to fd80412 Compare March 1, 2026 17:33
Replaces the unconditional _G.arg overwrite with an opt-in API.
The runtime helper is only included when getModuleVarargs() is used.
@jdonaldson jdonaldson force-pushed the lua-global-varargs branch from fd80412 to 79bf1d2 Compare March 5, 2026 00:02
@jdonaldson
Copy link
Member Author

Finished up a total rewrite. This uses a lua feature module to capture the args, rather than capturing it at the start of every script.

@jdonaldson jdonaldson changed the title [lua] Capture module-level varargs into _G.arg for Sys.args() [lua] Add lua.Lib.getModuleVarargs() for module-level varargs capture Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants